package com.clstu.qqserver.service;

import com.clstu.qqcommon.Message;
import com.clstu.qqcommon.MessageType;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

/**
 * 根据用户id与对应的用户保持连接的线程,(根据客户端的消息进行对应的处理)
 */
public class ServerConnectClientThread extends Thread{
    private final Socket socket;//用户与服务器对应的socket对象
    private final String userID;//用户id

    public ServerConnectClientThread(Socket socket, String userID) {
        this.socket = socket;
        this.userID = userID;
    }


    @Override
    public void run() {
        System.out.println("服务端在和"+userID+"保持连接,等待接受数据");

        //当一个线程启动时,首先看是否有未发送的离线消息,有就先发送了
        ArrayList<Message> myMessage = OfflineMessages.getMyMessage(userID);
        if(myMessage != null){
            for (Message m:myMessage ) {
                sentMessage(m);
            }
            OfflineMessages.removeMessage(userID);//删除已经发送的消息
        }
        label:
        while (true){
            try {
                ObjectInputStream ois = new  ObjectInputStream(socket.getInputStream());

                //注意,下面这句注释掉的 千万不能随便乱写,有需要才写,不然容易引起错乱!!!!(被卡了2小时!!!)
//                ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                Message message = (Message) ois.readObject();//一直等待发送消息

                switch (message.getMesType()) {
                    //如果是请求列表的消息
                    case MessageType.MESSAGE_GET_ONLINE_LIST:
                        System.out.println("用户" + message.getSender() + "获取了在线用户列表...");
                        //构造的用于回复消息的对象
                        Message msg = new Message();
                        msg.setMesType(MessageType.MESSAGE_RET_ONLINE_LIST);
                        msg.setContent(ServerConnectClientThreadManager.getOline());
                        msg.setSender(msg.getGetter());
                        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                        oos.writeObject(msg);
                        break;

                    //如果是退出的消息
                    case MessageType.MESSAGE_EXIT:
                        System.out.println("用户" + userID + " 已下线....");
                        ois.close();
                        userOutline();
                        break label;

                    //如果是普通聊天消息/或者文件消息
                    case MessageType.MESSAGE_COMMON_MES:
                    case MessageType.MESSAGE_SENT_FILE:

                        //转发该消息到指定接收者
                        ServerConnectClientThread sCCThread = ServerConnectClientThreadManager.getServerConnectClientThread(message.getGetter());
                        //判断接收方是否存在或者自己给自己发消息
                        if (sCCThread != null && sCCThread != this) {
                            sCCThread.sentMessage(message);
                        } else {
                            boolean exist = isUserExist(message);
                            if (!exist) {//接收方不存在则发送提示
                                Message msg1 = new Message();//构造的用于回复消息的对象
                                msg1.setMesType(MessageType.MESSAGE_COMMON_MES);
                                msg1.setContent("你的消息未转发,接收方不存在(或者接收方是自己)....");
                                msg1.setSender("服务器");
                                ObjectOutputStream oos1 = new ObjectOutputStream(socket.getOutputStream());
                                oos1.writeObject(msg1);
                            }
                        }
                        break;

                    //如果是群发消息
                    case MessageType.MESSAGE_SENT_ALL:
                        //群发到所有的线上用户
                        HashMap<String, ServerConnectClientThread> userConnectionThreadMap = ServerConnectClientThreadManager.getUserConnectionThreadMap();
                        Set<String> userIds = userConnectionThreadMap.keySet();
                        for (String uid : userIds) {
                            //不给自己转发
                            if (!userID.equals(uid)) {
                                userConnectionThreadMap.get(uid).sentMessage(message);
                            }
                        }
                        break;
                    default:
                        System.out.println("其他消息类型等会再说...");
                        break;
                }
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
                System.out.println("用户"+userID+"因为异常退出,已下线...");
                userOutline();
                break;
            }

        }
    }

    /** 判断是否接收方存在 */
    private boolean isUserExist(Message message) {
        boolean exist = false;
        Set<String> users = QQServer.getValidUsers().keySet();
        for (String u : users) {
            //如果对方只是离线,就把消息/文件保持在服务器上,等用户上线后发送给该用户
            if (u.equals(message.getGetter()) && !u.equals(userID)) {//根据对象存入
                OfflineMessages.addOffMessage(message);//存入离线消息列表中
                exist = true;
            }
        }
        return exist;
    }

    //该方法使自己线程结束,即将该用户下线
    public void userOutline(){
        ServerConnectClientThreadManager.removeClientConnectServerThread(userID);//从线程管理器中移出
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Socket getSocket() {
        return socket;
    }

    public void sentMessage(Message m){
        try {
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            oos.writeObject(m);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String getUserID() {
        return userID;
    }
}
